Repository navigation
feat: keep every display in step with one revision counter per kind of data (#325) - #339
Merged
Merged
Conversation
…f data (#325) A change on one display now shows on the others within 15 seconds on any install, and within a second where the event stream reaches the browser. Server (utils/householdChanges.js): - A revision counter for each kind of household data: chores, users, prizes, settings, calendar. An onResponse hook moves them for every successful write under the household routes, so no route can forget; a chore or prize write also moves users, for clam totals. The nightly job, calendar sync (only when the cache changed) and calendar routines move them too. Counters start from a random base, so a restart reads as everything changed. - GET /api/changes returns them with an ETag, and 304 when nothing moved. - Each burst of changes goes out on the event stream as household.changed { domains, revisions }, a new catalog event plugins can declare. Client (utils/householdChanges.js): - A display checks GET /api/changes every 15 seconds while visible and at once when it becomes visible again; a phone checks only when it becomes visible. The stream's household.changed is the fast path; both feed one deduplicated notification. - Coarse by design: subscribers learn which kinds moved and reload them. The Chores widget reloads on chores, users, prizes or settings; the calendar and the screensaver agenda on calendar; household settings (appearance, vacation, control limits) on settings; plugins that declare household.changed are told. Co-Authored-By: Claude Opus 5.5 <[email protected]>
adamecker
pushed a commit
to adamecker/HomeGlow
that referenced
this pull request
Oct 26, 2026
… revision counter jherforth#339, dimming jherforth#334, Save layout jherforth#336, chore perf jherforth#324, admin jherforth#330/jherforth#331/jherforth#332, PIN hardening jherforth#329 Conflicts resolved taking upstream's rewrite, preserving fork(prod) features: - displayDim.js: upstream jherforth#334 base plus fork-only kiosk URL dim overrides and LCD pixel shift (both absent upstream) - ChoreWidget/app.jsx/ChoreSchedulesTab: upstream jherforth#324/jherforth#336 rework
adamecker
pushed a commit
to adamecker/HomeGlow
that referenced
this pull request
Oct 31, 2026
…herforth#347) Per-plugin storage counters on the jherforth#339 path: a write moves only its own plugin's counter, pushed over the event stream within a second and caught up by the 15s GET /api/changes check, so plugins need polling only as the older-server fallback. The event carries the plugin id only, never a key; the frame reloads what it uses. Counters are created on a plugin's first storage write and dropped when its data is purged, so the set grows and shrinks with installed plugins; the ETag is built from the five fixed kinds plus the plugin kinds in sorted order. A frame receives only its own plugin's events: the dashboard subscribes per plugin id and forwards nothing else into the frame. Covered write paths: PUT, DELETE and POST increment through the request hook, server-side reactions, and uninstall with purge; reactions never fire on a storage change itself, which would self-trigger. The guide documents the no-key payload and the per-plugin scoping. Tests: per-path and isolation coverage in server/tests (unit + real server, incl. the stream carrying no key) and client tracker tests (a frame's subscription hears only its own plugin, baseline rules, prune on uninstall, reinstall reading as changed).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #325, with the decisions from the issue:
What it does
A change on one display (a chore ticked, a prize approved, vacation turned on, a calendar event added) shows on every other display:
The nightly job and calendar sync reach every display the same way.
Server:
utils/householdChanges.jschores,users,prizes,settingsandcalendar.onResponsehook moves the counters for every successful write under the household routes, so no route can forget to.users, because it changes clam totals./api/settings/search, a calendar source's test).GET /api/changes:{ chores, users, prizes, settings, calendar }with anETag, and304when nothing moved. The counters start from a random base, so after a restart every display reloads everything once.household.changed{ domains, revisions }, coalesced over 100 ms. It's a new catalog event that plugins can declare.Client:
utils/householdChanges.jshousehold.changedfeeds the same notification, so a change is reported once, whichever saw it first.household.changed: they're told which kinds changed.Left out on purpose
Worth knowing: every display now keeps the event stream open, not only those with event-subscribing plugins. Where the stream doesn't reach the browser, nothing breaks; the 15-second checks carry it.
Testing
Edge, two displays on one server, demo data. 8 of 8 checks pass:
304while nothing changes;Server tests:
householdChanges.test.js: the route mapping, reads and failures, coalescing, the random base;householdChangesRoutes.test.js, on a real server:304with the ETag, each write moving its kinds (a completion moves chores and users), reads and failures moving nothing, the nightly job, and the stream event;Server
npm test: 656 pass.Client tests:
householdChanges.test.js: notifications only for the kinds asked for, the baseline,If-None-Matchand304, a restart, the 15-second cadence and visibility, the phone mode, stopping with the last subscriber, and recovery after a failed check. Clientvitest(795),check:i18nandbuildpass.Dev setup: the dev server is cross-origin, so
If-None-Matchis allowed andETagexposed for it. Production is same-origin.Closes #325.
🤖 Generated with Claude Code